﻿using LittleBee.CellStore.UserControls;
using LittleBee.IDAL;
using LittleBee.JsonRpc;
using LittleBee.Utils;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using LittleBee.CellStore.Dialog;

namespace LittleBee.CellStore
{
	public partial class FormMain : Form
	{
		readonly JsonRpcClient _CellServiceRpcClient = new JsonRpcClient(65432);

		readonly LBAccess _dba = LBAccess.Instance;
		private Store? _store;
		private StoreCell? _cell;
		UserControl? _ucCurrent;

		static readonly Dictionary<string, Type> _dctCellClass = new Dictionary<string, Type>();
		public static Dictionary<string, Type> CellClasses => _dctCellClass;

		public FormMain()
		{
			try
			{
				_CellServiceRpcClient.OnJsonRpcException += JsonRpcExceptionHandler;
				_CellServiceRpcClient.Start();
				//CreateAndUpdateIotUserDatabase();
				//CreateAndUpdateIotDatabase();

				InitializeComponent();
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message + "\n" + ex.StackTrace);
			}
		}

		private void JsonRpcExceptionHandler(JsonRpcExceptionEventArg args)
		{
			MessageBox.Show($"JsonRpc request failed: {nameof(args.ErrorType)}:{args.Response}");
		}

		private void FormMain_Load(object sender, EventArgs e)
		{
			Init_CellBaseClassList();
			Init_ToolStripComboBox();
		}

		private void Init_CellBaseClassList()
		{
			Assembly assembly = Assembly.LoadFrom("libCell.dll");

			Type type = assembly.GetType("LittleBee.Cells.Cell")!;

			foreach (var item in assembly.GetTypes())
			{
				if (item.IsClass && item.IsSubclassOf(type))
				{
					_dctCellClass[item.FullName!] = item;
				}
			}
		}

		private void Init_ToolStripComboBox()
		{
			if (tscbStore.ComboBox.DataSource == null)
			{
				BindingSource bs;
				tscbStore.BeginUpdate();
				_dba.StoreQueryStoreList(out DataTable? dtStore);

				tscbStore.ComboBox.DisplayMember = "name";
				tscbStore.ComboBox.ValueMember = "store_id";

				bs = new BindingSource
				{
					DataSource = dtStore
				};
				tscbStore.ComboBox.DataSource = bs;

				tscbStore.EndUpdate();
			}
		}

		private void TscbStore_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (tscbStore.ComboBox.SelectedItem == null)
			{
				_store = null;
			}
			else
			{
				DataRowView selItem = (tscbStore.ComboBox.SelectedItem as DataRowView)!;

				Int64 nStoreID = selItem.Row.Field<Int64>("store_id");
				if (_store != null && nStoreID == _store.StoreID)
					return;

				_store = new Store(nStoreID, 
					selItem.Row.Field<string>("store_uuid")!,
					selItem.Row.Field<string>("name")!,
					selItem.Row.Field<string>("description")!);

			}
			_cell = null;

			if (_store != null)
			{
				_dba.StoreQueryCellList(_store.StoreID, out DataTable? dtCells);

				if (dtCells != null)
				{
					tscbCell.BeginUpdate();

					if (tscbCell.ComboBox.DataSource == null)
					{
						tscbCell.ComboBox.DataSource = new BindingSource();
					}
					(tscbCell.ComboBox.DataSource as BindingSource)!.DataSource = dtCells;
					tscbCell.ComboBox.DisplayMember = "type";
					tscbCell.ComboBox.ValueMember = "cell_id";
					tscbCell.ComboBox.SelectedIndex = -1;

					if (tscbCell.ComboBox.Items.Count > 0)
						tscbCell.ComboBox.SelectedIndex = 0;

					tscbCell.EndUpdate();
				}
			}
		}

		static readonly string _strCellContents = @"
		[
			{name:'属性',type:'UCCellPointers'},
			{name:'业务逻辑',type:'UCBusinessInterface'},
			{name:'结构',type:'UCCellProperty'},
			{name:'列表',type:'UCCellProperty'},
			{name:'界面',type:'UCCellProperty'},
			{name:'通讯设置',type:'UCCommSettings'},
			{name:'IO',type:'UCCellProperty'},
			{name:'库',type:'UCCellLibrary'}
		]";
		//{name:'代码',type:'UCCellCode'}

		static readonly JArray _jaCellContents = JArray.Parse(_strCellContents);

		private void TscbCell_SelectedIndexChanged(object sender, EventArgs e)
		{
			if (tscbCell.ComboBox.SelectedItem == null)
			{
				tvCellContents.Nodes.Clear();
				splitContainer1.Panel2.Controls.Clear();
			}
			else
			{
				DataRowView selItem = (tscbCell.ComboBox.SelectedItem as DataRowView)!;

				Int64 nCellID = selItem.Row.Field<Int64>("cell_id");
				if (_cell != null && nCellID == _cell.CellID)
					return;

				if (_dba.StoreQueryCellInfo(nCellID, out DataTable? dtCellInfo)
					&& _dba.StoreQueryCellPointers(nCellID, out DataTable? dtPointers))
				{
					
					_cell = new StoreCell(dtCellInfo!, dtPointers!);
					_cell.PropertyChanged += HandleCellPropertyChanged!;
				}

				tvCellContents.BeginUpdate();

				tvCellContents.Nodes.Clear();
				TreeNode tnCurr = tvCellContents.Nodes.Add($"{_cell!.CellID}", $"Cell类型: {_cell.CellType}");
				tnCurr.Tag = new KeyValuePair<Type, StoreCell>(typeof(UCCellProperty), _cell);

				foreach (var item in _jaCellContents)
				{
					TreeNode tnItem = new TreeNode
					{
						Text = item["name"]!.Value<string>(),
						Tag = new KeyValuePair<Type, StoreCell>(Type.GetType("LittleBee.CellStore.UserControls." + item.Value<string>("type"))!, _cell)
					};

					tnCurr.Nodes.Add(tnItem);
				}
				tvCellContents.ExpandAll();
				tvCellContents.SelectedNode = tnCurr;

				tvCellContents.EndUpdate();
			}
		}

		static readonly string _strCreateStoreText = @"[
			{name:'StoreName',type:'text',hit:'仓库名称：'},
			{name:'StoreDesc',type:'text',hit:'仓库描述：'},
		]";

		private void CreateStoreToolStripMenuItem_Click(object sender, EventArgs e)
		{

			var jaInputs = JArray.Parse(_strCreateStoreText);
			bool blRet = MultiInputBox.InputBox("创建仓库", jaInputs, out JObject joReturns, 400);
			if (blRet == false)
				return;

			string strStoreName = joReturns.Value<string>("StoreName")!;
			string strStoreDesc = joReturns.Value<string>("StoreDesc")!;

			if (_dba.IsStoreExist(strStoreName) == false)
			{
				if (_dba.StoreCreateStore(strStoreName, strStoreDesc, out _) == true)
				{
					_dba.StoreQueryStoreList(out DataTable? dtStore);
					(tscbStore.ComboBox.DataSource as BindingSource)!.DataSource = dtStore;
					tscbStore.ComboBox.SelectedIndex = -1;

					if (tscbStore.ComboBox.Items.Count > 0)
						tscbStore.ComboBox.SelectedIndex = tscbStore.ComboBox.Items.Count - 1;


				}
				else
				{
					MessageBox.Show($"创建Cell Store: {strStoreName} 失败！", "创建Cell Store");
				}
			}
			else
			{
				MessageBox.Show($"Cell Store: {strStoreName}已经存在！");
			}
		}

		private int QueryStoreIndex(string strStoreName, DataTable dtStore)
		{
			int nRet = 0;
			foreach (DataRow item in dtStore.Rows)
			{
				if (item.Field<string>("name") == strStoreName)
				{
					return nRet;
				}

				++nRet;
			}

			return -1;
		}

		string _strCreateCellText = @"[
			{name:'CellName',type:'text',hit:'请输入Cell名称：',params:{},rules:[{OnExit:'NotEmpty', ErrorHit:'Cell名称是空'}]},
			{name:'CellType',type:'text',hit:'请输入Cell类型：',rules:[{OnExit:'NotEmpty', ErrorHit:'Cell类型是空'}]},
			{name:'CellDesc',type:'text',hit:'请输入Cell描述：'},
			{name:'CellClass',type:'combo',hit:'请输入Cell类型：',list:[]}
		]";

		private void CreateCellToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (_store == null)
			{
				MessageBox.Show($"请先选择仓库", "创建Cell", MessageBoxButtons.OK);
				return;
			}

			var jaInputs = JArray.Parse(_strCreateCellText);
			foreach (var item in jaInputs)
			{
				if (item.Value<string>("name") == "CellClass")
				{
					JArray jaList = (item["list"] as JArray)!;

					foreach (var itmCellClass in _dctCellClass)
					{
						JObject joCellClass = new JObject();

						joCellClass["key"] = itmCellClass.Key;
						joCellClass["value"] = itmCellClass.Value.ToString();
						jaList.Add(joCellClass);
					}
				}
			}

			bool blRet = MultiInputBox.InputBox("创建Cell", jaInputs, out JObject joReturns, 400);
			if (blRet == false)
				return;

			string strCellName = joReturns.Value<string>("CellName")!;
			string strCellType = joReturns.Value<string>("CellType")!;
			string strCellDesc = joReturns.Value<string>("CellDesc")!;
			string strCellClass = joReturns.Value<string>("CellClass")!;
			if (_dba.IsStoreCellExist(_store.StoreID, strCellType) == false)
			{
				CellCodeGenerator cg = new CellCodeGenerator
				{
					CellType = strCellType,
					CellBaseClass = strCellClass
				};
				string strCellCode = cg.GeneratedCode();

				if (_dba.StoreCreateCell(_store.StoreID, strCellType, strCellName, strCellDesc, strCellClass, strCellCode, out Int64 nCell_ID) == true)
				{
					_dba.StoreQueryCellList(_store.StoreID, out DataTable? dtStore);
					(tscbCell.ComboBox.DataSource as BindingSource)!.DataSource = dtStore;
					tscbCell.ComboBox.SelectedIndex = -1;

					if (tscbCell.ComboBox.Items.Count > 0)
						tscbCell.ComboBox.SelectedIndex = tscbCell.ComboBox.Items.Count - 1;

					CreateCellSharedPointers(strCellClass);
				}
				else
				{
					MessageBox.Show($"创建Cell类型: {strCellType} 失败！", "创建Cell类型");
				}
			}
			else
			{
				MessageBox.Show($"Cell类型: {strCellType}已经存在！");
			}
		}

		private void CreateCellSharedPointers(string strCellClass)
		{
			Assembly assembly = Assembly.LoadFrom("libCell.dll");

			Type type = assembly.GetType(strCellClass)!;

			var GetCellSharedPointers = type.GetMethod("GetCellSharedPointers")!;
			JArray? jaPointers = null;
			object?[] pars = new object?[] { jaPointers };
			GetCellSharedPointers.Invoke(GetCellSharedPointers, pars);

			jaPointers = (pars[0] as JArray)!;
			foreach (var item in jaPointers)
			{
				//string newPid = GetNewPid();
				DataRow drNew = _cell!.DataTableCellPointers.NewRow();
				drNew.BeginEdit();
				drNew["cell_id"] = _cell.CellID;
				drNew["pid"] = item.Value<string>("pid");
				drNew["name"] = item.Value<string>("name");
				drNew["description"] = item.Value<string>("description");
				drNew["attribute"] = item.Value<UInt64>("attribute");
				drNew["type"] = item.Value<string>("type");
				drNew["value"] = item["value"];
				drNew["helper"] = item["helper"];
				drNew.EndEdit();
				_cell.DataTableCellPointers.Rows.Add(drNew);
			}

			_cell!.Save();
		}

		private string GetNewPid()
		{
			int i = 1;
			string strNewPid = $"NewPid_{i:d03}";

			while (_cell!.DataTableCellPointers.Select($"pid = '{strNewPid}'").Length == 1)
			{
				++i;
				strNewPid = $"NewPid_{i:d03}";
			}

			return strNewPid;
		}

		private Dictionary<string, Action<UserControl>> _dctUCCallBackAction = new Dictionary<string, Action<UserControl>>
		{
			{ "LittleBee.CellStore.UserControls.UCBusinessInterface",  (x) => {
				}
			},
			{ "LittleBee.CellStore.UserControls.UCCellCode", (x) => {
				}
			},
			{ "LittleBee.CellStore.UserControls.UCCellPointers", (x) => {
				}
			},
			{ "LittleBee.CellStore.UserControls.UCCellProperty", (x) => {
				}
			}
		};

		private static void HandleCodeComit(EventArgs arg)
		{
			
		}

		private void TvCellContents_AfterSelect(object sender, TreeViewEventArgs e)
		{
			splitContainer1.Panel2.Controls.Clear();

			var tag = (KeyValuePair<Type, StoreCell>)e.Node!.Tag;
			_ucCurrent = Assembly.GetExecutingAssembly().CreateInstance(tag.Key.FullName!) as UserControl;
			_ucCurrent!.Tag = tag.Value;
			_ucCurrent.Dock = DockStyle.Fill;
			splitContainer1.Panel2.Controls.Add(_ucCurrent);
		}

		private void MiSave_Click(object sender, EventArgs e)
		{
			_cell!.Save();
		}

		private void MiOpenCell_Click(object sender, EventArgs e)
		{

		}

		private void HandleCellPropertyChanged(object sender, PropertyChangedEventArgs args)
		{
			switch (args.PropertyName)
			{
				case "type":
					{
						TreeNode tnCell = tvCellContents.SelectedNode;
						tnCell.Text = $"Cell类型: {_cell!.CellType}";
					}
					break;
				case "name":
					{
						//TreeNode tnCell = tvCellContents.SelectedNode;
						//tnCell.Text = $"Cell类型: {_cell.CellType}";
					}
					break;
				case "description":
					{
						//TreeNode tnCell = tvCellContents.SelectedNode;
						//tnCell.Text = $"Cell类型: {_cell.CellType}";
					}
					break;
				case "class":
					{
						//TreeNode tnCell = tvCellContents.SelectedNode;
						//tnCell.Text = $"Cell类型: {_cell.CellType}";
					}
					break;
				case "CommSet":
                    {
						//TreeNode tnCell = tvCellContents.SelectedNode;
						//tnCell.Text = $"Cell类型: {_cell.CellType}";
					}
					break;
			}
		}

		private void MiExport_Click(object sender, EventArgs e)
		{
			SaveFileDialog sfd = new SaveFileDialog();

			if (sfd.ShowDialog() == DialogResult.OK)
			{
				_cell!.Save();
				ExportCell(sfd.FileName);
			}	
		}

		private void ExportCell(string strFileName)
		{
			JObject joCellPointer = _cell!.GetCellExportInfo();

			File.WriteAllText(strFileName, joCellPointer.ToString());

			return ;
		}

		private void TsmiInstallCell(object sender, EventArgs e)
		{
			if (_cell == null)
			{
				MessageBox.Show("Not one cell selected!");
				return;
			}
			_cell.Save();

			if (_CellServiceRpcClient.ConnectedState == false)
			{
				MessageBox.Show("未连接到数据服务中心！", "错误信息", MessageBoxButtons.OK);
				return;
			}

			JObject joParams = new JObject
			{
				["cell_type"] = _cell.CellType,
				["cell_uuid"] = _cell.CellUUID,
			};

			bool blExist = true;
			Int64 cell_id = 0;

			try
			{
				JObject joResp = _CellServiceRpcClient.CallMehod("IsCellTypeExist", joParams)!;
				if (joResp.TryGetValue("result", out JToken? jtResult) == false)
				{
					MessageBox.Show("Unknown internal error", "Exception occurred");
					return;
				}

				JObject joResult = (jtResult as JObject)!;

				blExist = joResult!.Value<bool>("return");
				if (blExist == true)
					cell_id = joResult.Value<Int64>("cell_id");

				joParams = new JObject
				{
					["cell_type"] = _cell.CellType,
					["cell_uuid"] = _cell.CellUUID,
					["cell_info"] = _cell.GetCellExportInfo()
				};

				if (blExist == true)
				{
					DialogResult drRet = MessageBox.Show($"Cell Type: {_cell.CellType} has exist! Confirm to reinstall?",
						$"Install Cell Type", MessageBoxButtons.YesNoCancel);

					joParams["cell_id"] = cell_id;
					if (drRet == DialogResult.Yes)
					{
						joParams["force"] = true;
					}
					else if (drRet == DialogResult.Cancel)
					{
						return;
					}
				}

				_CellServiceRpcClient.CallMethodAsync("InstallCellType", joParams).ContinueWith((x) =>
				{
					JObject? joResp1 = x.Result.Response;
					bool blResult1 = joResp1!.Value<bool>("result");

					if (blResult1 == true)
						MessageBox.Show(this, $"Install Cell Type Success.");
					else
						MessageBox.Show($"Install Cell Type Failed.");
				}, TaskContinuationOptions.ExecuteSynchronously);
			}
			catch (TimeoutException ex)
			{
				Console.WriteLine($"JsonRpc call timeout : {ex.Message}");
			}
		}

		private void toolStripMenuItem4_Click(object sender, EventArgs e)
		{
			ManageCellFrame manCellFrame = new ManageCellFrame();
			manCellFrame.CellDataSource = tscbCell.ComboBox.DataSource;

			DialogResult drRet = manCellFrame.ShowDialog();
			if (drRet == DialogResult.OK)
			{

			}
		}
	}
}
